import { defaultsDeep } from 'lodash';
import * as echarts from 'echarts/core';
import { LegendComponent } from 'echarts/components';
import { GraphChart } from 'echarts/charts';
echarts.use([GraphChart, LegendComponent])
export default function GraphChart1(options) {
    this.options = defaultsDeep(options, this.defaultOption())
    this.init()
    this.state = 0 //0 初始化未渲染，1 已渲染有数据，2 已渲染但无数据

}
GraphChart1.prototype = {
    /**
    * @Author: zhangjinhao
    * @Date 2024-05-27 09:32:04
    * @Describe: 初始化
    */
    init() {
        this.chartContainer = document.getElementById(`${this.options.chartId}`)
        this.buildLineOption() //处理连线样式
        this.chart = echarts.init(document.getElementById(`${this.options.chartId}`))
        this.bindClickEvent()
    },
    /**
     * 设置图形源数据
     * @param data
     */
    setProps({ data }) {
        this.data = data;
        //渲染
        this.render();
    },
    render() {
        this.chart && this.chart.resize()
        this.updateLayoutOption()
        if (this.data && this.data.length) {
            let { nodes, links, categories } = this.buildGraphicData();
            this.chartOption = {
                backgroundColor: this.options.backgroundColor, //背景颜色
                //图例
                legend: [Object.assign({
                    data: categories.map(function (a) {
                        return a.name;
                    })
                }, this.options.legendOption)],
                //坐标轴，坐标轴区域与图形实际绘制区域贴合，用来做绝对定位作用，但是不显示坐标轴区域
                grid: {
                    show: true,
                    left: this.options.innerPadding.left,
                    right: this.options.innerPadding.right,
                    bottom: this.options.innerPadding.bottom,
                    top: this.options.innerPadding.top,
                    containLabel: true
                },
                //x轴
                xAxis: [Object.assign({
                    min: 0,
                    max: this.chartWidth,
                    position: "top"
                }, this.options.axisOption)],
                //Y轴
                yAxis: [Object.assign({
                    min: 0,
                    max: this.chartHeight,
                    inverse: true
                }, this.options.axisOption)],
                series: [
                    {
                        name: '服务单位',
                        type: 'graph',
                        coordinateSystem: 'cartesian2d',
                        data: nodes,
                        links: links,
                        categories: categories,
                        //roam: true, //是否开启鼠标缩放和平移漫游
                        edgeSymbol: ['circle', 'circle'],
                        edgeSymbolSize: 1,
                        lineStyle: this.lineStyle,
                    }
                ]
            };
            console.log(this.chartOption, '==this.chartOption');
            this.chart.setOption(this.chartOption);
            // this.updatePopup();
            this.status = 1;
        } else {
            this.chart && this.chart.clear();
            this.status = 2;
        }
    },
    // 更新布局相关参数
    updateLayoutOption() {
        //图形的实际宽度
        this.chartWidth = document.getElementById(`${this.options.chartId}`).clientWidth
        this.chartHeight = document.getElementById(`${this.options.chartId}`).clientHeight
    },
    /**
    * @Author: zhangjinhao
    * @Date 2024-05-27 10:03:41
    * @Describe: 绑定click事件
    */
    bindClickEvent() {
        this.chart.on('click', (params) => {
            params.dataType === "node" && !params.data.isMainNode && this.openPopup(params.data)
        })
    },
    /**
    * @Author: zhangjinhao
    * @Date 2024-05-27 09:45:25
    * @Describe: 处理连线样式
    */
    buildLineOption() {
        let lineColor = this.options.lineStyle.color;
        try {
            if (lineColor) {
                //拆分颜色代码，注意：此处限定为16进制颜色代码，使用rgb\rgba需重写拆分方法
                const colorList = lineColor.split(",");
                const colorLen = colorList.length;
                if (colorLen > 1) {
                    //渐变色，渐变区间自动分配
                    const scale = 1 / (colorLen - 1);
                    const colorStops = [];
                    colorList.forEach((color, index) => {
                        colorStops.push({
                            color,
                            offset: index * scale
                        })
                    });
                    lineColor = {
                        type: 'linear',
                        x: 0,
                        y: 0,
                        x2: 0,
                        y2: 1,
                        colorStops,
                        global: false // 缺省为 false
                    };
                }
            }
        } catch (e) {
            console.error("处理图形连接线颜色出错", e)
        }
        this.lineStyle = Object.assign({}, this.options.lineStyle, lineColor ? { color: lineColor } : null);
    },
    buildGraphicData() {
        const { data, chartWidth, chartHeight } = this;
        const {
            nodeOpacity,      //节点背景颜色透明度，为0则不绘制背景颜色，不需要背景颜色时可配置为0
            distanceMinScale, //引线长度最小比例
            distanceMaxScale, //引线长度最大比例
            sizeMinScale,     //图标大小最小比例
            sizeMaxScale,     //图标大小最大比例
            mainIconSize,   //中心节点图标大小
            maxIconSize       //副节点最大图标大小
        } = this.options;

        let topMaxValue = 0;
        let bottomMaxValue = 0;

        const categories = [];
        const categoriesMap = {};

        //主节点
        const mainNodes = [];
        //顶部节点
        const topNodes = [];
        //底部节点
        const bottomNodes = [];
        //图标效果叠加节点
        const effectNodes = [];
        const nodesMap = {};

        const links = [];
        data.forEach(d => {
            let f_legend = d.F_LEGEND,
                f_legend_color = d.F_LEGEND_COLOR,
                f_legend_icon = d.F_LEGEND_ICON ? d.F_LEGEND_ICON.split(",") : [],
                t_legend = d.T_LEGEND,
                t_legend_color = d.T_LEGEND_COLOR,
                t_legend_icon = d.T_LEGEND_ICON ? d.T_LEGEND_ICON.split(",") : [];
            if (f_legend && !categoriesMap.hasOwnProperty(f_legend)) {
                categoriesMap[f_legend] = categories.length;
                categories.push({
                    name: f_legend,
                    itemStyle: {
                        color: f_legend_color,
                        opacity: 1
                    },
                    iconList: f_legend_icon,
                    symbol: "circle"
                });
            }
            if (t_legend && !categoriesMap.hasOwnProperty(t_legend)) {
                categoriesMap[t_legend] = categories.length;
                categories.push({
                    name: t_legend,
                    itemStyle: {
                        color: t_legend_color,
                        opacity: 1
                    },
                    iconList: t_legend_icon,
                    symbol: "circle"
                });
            }

            let f_id = "mainNode_" + d.F_ID,
                f_name = d.F_NAME,
                f_icon = d.F_ICON,
                t_id = "viceNode_" + d.T_ID,
                t_name = d.T_NAME,
                t_icon = d.T_ICON,
                isTop = d.T_ISTOP,
                value = d.T_VALUE;

            if (!nodesMap.hasOwnProperty(f_id)) {
                nodesMap[f_id] = true;

                let position = [chartWidth / 2, chartHeight * 0.5];
                let node = Object.assign(
                    {
                        id: f_id,
                        name: f_name,
                        value: position,
                        label: Object.assign({}, this.options.mainLabel),
                        itemStyle: {
                            opacity: nodeOpacity
                        },
                        symbolSize: mainIconSize * 0.6,
                        isMainNode: true,
                        info: d
                    },
                    !!f_icon ? { iconList: f_icon.split(",") } : null,
                    f_legend && categoriesMap.hasOwnProperty(f_legend) ? { category: categoriesMap[f_legend] } : null,
                );
                mainNodes.push(node);
                this.mainPosition = position;
            }

            if (!nodesMap.hasOwnProperty(t_id)) {
                nodesMap[t_id] = true;
                let node = Object.assign({
                    id: t_id,
                    name: t_name,
                    label: Object.assign({}, this.options.otherLabel),
                    itemStyle: {
                        opacity: nodeOpacity
                    },
                    info: d,
                    zbz: value //指标值
                },
                    !!t_icon ? { iconList: t_icon.split(",") } : null,
                    t_legend && categoriesMap.hasOwnProperty(t_legend) ? { category: categoriesMap[t_legend] } : null)

                if (isTop) {
                    topMaxValue = Math.max(topMaxValue, value);
                    topNodes.push(node);
                } else {
                    bottomMaxValue = Math.max(bottomMaxValue, value);
                    bottomNodes.push(node);
                }
            }

            links.push({
                source: f_id, target: t_id
            })
        });
        let cutAngle = Math.atan((chartHeight - maxIconSize) / (chartWidth - maxIconSize)) / (Math.PI / 180);
        let topLen = topNodes.length;
        if (topLen) {
            let angleScale = Math.round(160 / topLen);
            topNodes.forEach((node, index) => {
                let x, y;
                let scale = node.zbz / topMaxValue;
                let sizeScale = Math.min(sizeMaxScale, Math.max(sizeMinScale, scale));
                let symbolSize = Math.round(maxIconSize * sizeScale);
                let distanceScale = Math.min(distanceMaxScale, Math.max(distanceMinScale, scale));
                let angle = 170 - (index + 0.5) * angleScale;
                angle = angle % 90 === 0 ? angle - 1 : angle;
                if (angle < 180 - cutAngle && angle > cutAngle) {
                    //落在中间部分
                    x = chartWidth / 2 + distanceScale * (chartHeight - maxIconSize) / 2 / Math.tan(angle * (Math.PI / 180));
                    y = chartHeight / 2 - (chartHeight - maxIconSize) / 2 * distanceScale;
                } else {
                    //落在两侧
                    y = chartHeight / 2 - distanceScale * (chartWidth - maxIconSize) / 2 * Math.abs(Math.tan(angle * (Math.PI / 180)));
                    if (angle <= cutAngle) {
                        x = chartWidth / 2 + (chartWidth - maxIconSize) * distanceScale / 2;
                    } else {
                        x = chartWidth / 2 - (chartWidth - maxIconSize) * distanceScale / 2;
                    }
                }
                node.angle = angle;
                node.value = [x, y];
                node.symbolSize = symbolSize * 0.6;
            });
        }

        let bottomLen = bottomNodes.length;

        if (bottomLen) {
            let middleCount = Math.round(bottomLen / 4);
            let middleAngleScale = 90 / middleCount;
            let leftCount = Math.round((bottomLen - middleCount) / 2);
            let leftAngleScale = 45 / leftCount;
            let rightCount = bottomLen - leftCount - middleCount;
            let rightAngleScale = 45 / rightCount;

            bottomNodes.forEach((node, index) => {
                let x, y, angle;
                let scale = node.zbz / bottomMaxValue;
                let sizeScale = Math.min(sizeMaxScale, Math.max(sizeMinScale, scale));
                let symbolSize = Math.round(maxIconSize * sizeScale);
                let distanceScale = Math.min(distanceMaxScale, Math.max(distanceMinScale, scale));

                if (index < leftCount) {
                    angle = 180 + (index + 0.5) * leftAngleScale;
                } else if (index < leftCount + middleCount) {
                    angle = 225 + (index - leftCount + 0.5) * middleAngleScale;
                } else {
                    angle = 315 + (index - leftCount - middleCount + 0.5) * rightAngleScale;
                }

                angle = angle % 90 === 0 ? angle - 1 : angle;
                if (angle > 180 + cutAngle && angle < 360 - cutAngle) {
                    //落在中间
                    x = chartWidth / 2 - distanceScale * (chartHeight - maxIconSize) / 2 / Math.tan(angle * (Math.PI / 180));
                    y = chartHeight / 2 + (chartHeight - maxIconSize) / 2 * distanceScale;
                } else {
                    //落在两侧
                    y = chartHeight / 2 + distanceScale * (chartWidth - maxIconSize) / 2 * Math.abs(Math.tan(angle * (Math.PI / 180)));
                    if (angle >= 360 - cutAngle) {
                        x = chartWidth / 2 + (chartWidth - maxIconSize) * distanceScale / 2;
                    } else {
                        x = chartWidth / 2 - (chartWidth - maxIconSize) * distanceScale / 2;
                    }
                }
                node.angle = angle;
                node.value = [x, y];
                node.symbolSize = symbolSize * 0.6;
            });
        }

        let nodes = mainNodes.concat(topNodes).concat(bottomNodes);
        nodes.forEach(node => {
            //叠加图标，当SQL数据中有图标字段时按照此数据叠加，默认按照当前图例的叠加图标进行叠加
            let iconList = node.iconList ? node.iconList : node.hasOwnProperty("category") ? categories[node.category].iconList : null;
            if (iconList && iconList.length) {
                iconList.forEach((url, index) => {
                    let effectNode = defaultsDeep({
                        id: `effect${index}_${node.id}`,
                        symbol: `image://${url}`,
                        symbolSize: node.symbolSize / 0.6,
                        itemStyle: {
                            opacity: 1
                        }
                    }, node)
                    // let effectNode = $.extend(true, {}, node, {
                    //     id: `effect${index}_${node.id}`,
                    //     symbol: `image://${url}`,
                    //     symbolSize: node.symbolSize / 0.6,
                    //     itemStyle: {
                    //         opacity: 1
                    //     },
                    // });
                    if (effectNode.label.show) {
                        effectNode.label.show = index === iconList.length - 1;
                    }
                    effectNodes.push(effectNode);
                });
                node.label.show = false;
            }
        });
        return { nodes: nodes.concat(effectNodes), links, categories };
    },
    defaultOption() {
        return {
            chartId: "chartId",
            chart: null,
            backgroundColor: "transparent", //背景颜色
            outerPadding: { left: 0, right: 0, top: 0, bottom: 0 },
            innerPadding: { left: 0, right: 0, top: 0, bottom: 0 },
            chartOption: null,
            nodeOpacity: 0.46,     //节点背景颜色透明度，为0则不绘制背景颜色，不需要背景颜色时可配置为0
            lineStyle: {
                color: "#ffcc66,#333333,#5096ff,#333333,#ffcc66", //连接线颜色，多个以,分割， 单个颜色代码线条颜色为单色，多个则为渐变色，置空则使用echarts默认颜色
                width: 2,
                curveness: 0
            },
            distanceMinScale: 0.3, //引线长度最小比例
            distanceMaxScale: 1,   //引线长度最大比例
            sizeMinScale: 0.6,     //图标大小最小比例
            sizeMaxScale: 1,       //图标大小最大比例
            mainIconSize: 300,   //中心节点图标大小
            maxIconSize: 200,      //副节点最大图标大小
            popupWidth: 500,        //弹框宽度
            popupHeight: 400,       //弹框高度
            popupOffset: [0, 0],      //弹框偏移量，默认为点击右侧节点弹框在中心节点左侧，点击左侧节点弹框在中心节点右侧，此配置在弹框位置基础上同向偏移
            mainLabel: {//中心节点文字配置
                show: true,
                color: "#ffffff",
                fontStyle: 'normal',
                fontSize: 40,
                fontWeight: 'bold',
                fontFamily: 'sans-serif',
            },
            otherLabel: {//副节点文字配置
                show: true,
                color: "#ffffff",
                fontStyle: 'normal',
                fontSize: 24,
                fontFamily: 'sans-serif',
            },
            legendOption: {
                show: true,
                bottom: 20,
                itemGap: 50,   //图例每项之间的间隔。横向布局时为水平间隔，纵向布局时为纵向间隔。
                itemWidth: 20, //图例图标宽
                itemHeight: 20,//图例图标高
                icon: 'rect',  //图例图形  方型
                orient: 'horizontal',  //图例列表的布局朝向。
                textStyle: {
                    color: "#fff",
                    fontSize: 20
                }
            },
            axisOption: {          //坐标轴相关属性
                type: "value",
                show: false,
                axisLine: { show: false },
                axisLabel: { show: false },
                axisTick: { show: false },
                splitLine: { show: false }
            }
        }
    }
}
